package com.kexio.file.storage;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.kexio.file.config.FileStorageProperties;

/**
 * 存储管理器
 * 
 * 统一管理多个存储提供者，提供存储路由和负载均衡功能
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Component
public class StorageManager {
    
    private static final Logger log = LoggerFactory.getLogger(StorageManager.class);
    
    @Autowired
    private FileStorageProperties storageProperties;
    
    @Autowired
    private List<StorageProvider> storageProviders;
    
    private Map<String, StorageProvider> providerMap = new HashMap<>();
    
    /**
     * 初始化存储提供者映射
     */
    public void initializeProviders() {
        providerMap.clear();
        
        for (StorageProvider provider : storageProviders) {
            providerMap.put(provider.getStorageType().toLowerCase(), provider);
            log.info("注册存储提供者: {}", provider.getStorageType());
        }
        
        log.info("存储管理器初始化完成，共注册 {} 个存储提供者", providerMap.size());
    }
    
    /**
     * 获取默认存储提供者
     * 
     * @return 存储提供者
     */
    public StorageProvider getDefaultProvider() {
        return getProvider(storageProperties.getDefaultProvider());
    }
    
    /**
     * 根据类型获取存储提供者
     * 
     * @param storageType 存储类型
     * @return 存储提供者
     */
    public StorageProvider getProvider(String storageType) {
        if (!StringUtils.hasText(storageType)) {
            storageType = storageProperties.getDefaultProvider();
        }
        
        StorageProvider provider = providerMap.get(storageType.toLowerCase());
        if (provider == null) {
            log.warn("未找到存储提供者: {}，使用默认提供者", storageType);
            provider = providerMap.get(storageProperties.getDefaultProvider().toLowerCase());
        }
        
        if (provider == null) {
            throw new RuntimeException("未找到可用的存储提供者");
        }
        
        return provider;
    }
    
    /**
     * 存储文件（使用默认提供者）
     * 
     * @param objectKey 对象键
     * @param inputStream 输入流
     * @param contentLength 内容长度
     * @param contentType 内容类型
     * @param metadata 元数据
     * @return 存储结果
     */
    public StorageResult storeFile(String objectKey, InputStream inputStream, 
                                   long contentLength, String contentType, Map<String, String> metadata) {
        return storeFile(null, null, objectKey, inputStream, contentLength, contentType, metadata);
    }
    
    /**
     * 存储文件
     * 
     * @param storageType 存储类型（可选，为空使用默认）
     * @param bucketName 存储桶名称（可选，为空使用默认）
     * @param objectKey 对象键
     * @param inputStream 输入流
     * @param contentLength 内容长度
     * @param contentType 内容类型
     * @param metadata 元数据
     * @return 存储结果
     */
    public StorageResult storeFile(String storageType, String bucketName, String objectKey, 
                                   InputStream inputStream, long contentLength, String contentType, 
                                   Map<String, String> metadata) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        // 确保存储桶存在
        provider.createBucketIfNotExists(bucketName);
        
        return provider.storeFile(bucketName, objectKey, inputStream, contentLength, contentType, metadata);
    }
    
    /**
     * 获取文件（使用默认提供者和存储桶）
     * 
     * @param objectKey 对象键
     * @return 文件输入流
     */
    public InputStream getFile(String objectKey) {
        return getFile(null, null, objectKey);
    }
    
    /**
     * 获取文件
     * 
     * @param storageType 存储类型（可选）
     * @param bucketName 存储桶名称（可选）
     * @param objectKey 对象键
     * @return 文件输入流
     */
    public InputStream getFile(String storageType, String bucketName, String objectKey) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.getFile(bucketName, objectKey);
    }
    
    /**
     * 删除文件
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param objectKey 对象键
     * @return 是否删除成功
     */
    public boolean deleteFile(String storageType, String bucketName, String objectKey) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.deleteFile(bucketName, objectKey);
    }
    
    /**
     * 检查文件是否存在
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param objectKey 对象键
     * @return 是否存在
     */
    public boolean fileExists(String storageType, String bucketName, String objectKey) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.fileExists(bucketName, objectKey);
    }
    
    /**
     * 获取文件信息
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param objectKey 对象键
     * @return 文件信息
     */
    public StorageFileInfo getFileInfo(String storageType, String bucketName, String objectKey) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.getFileInfo(bucketName, objectKey);
    }
    
    /**
     * 生成预签名下载URL
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param objectKey 对象键
     * @param expireMinutes 过期时间（分钟）
     * @return 预签名URL
     */
    public String generatePreSignedDownloadUrl(String storageType, String bucketName, 
                                              String objectKey, int expireMinutes) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.generatePreSignedDownloadUrl(bucketName, objectKey, expireMinutes);
    }
    
    /**
     * 复制文件
     * 
     * @param storageType 存储类型
     * @param sourceBucket 源存储桶
     * @param sourceKey 源对象键
     * @param destBucket 目标存储桶
     * @param destKey 目标对象键
     * @return 是否复制成功
     */
    public boolean copyFile(String storageType, String sourceBucket, String sourceKey, 
                           String destBucket, String destKey) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(sourceBucket)) {
            sourceBucket = storageProperties.getDefaultBucket();
        }
        if (!StringUtils.hasText(destBucket)) {
            destBucket = storageProperties.getDefaultBucket();
        }
        
        return provider.copyFile(sourceBucket, sourceKey, destBucket, destKey);
    }
    
    /**
     * 验证文件完整性
     * 
     * @param storageType 存储类型
     * @param bucketName 存储桶名称
     * @param objectKey 对象键
     * @param expectedHash 期望的哈希值
     * @return 验证结果
     */
    public boolean verifyFileIntegrity(String storageType, String bucketName, 
                                      String objectKey, String expectedHash) {
        StorageProvider provider = getProvider(storageType);
        
        if (!StringUtils.hasText(bucketName)) {
            bucketName = storageProperties.getDefaultBucket();
        }
        
        return provider.verifyFileIntegrity(bucketName, objectKey, expectedHash);
    }
    
    /**
     * 获取所有已注册的存储提供者类型
     * 
     * @return 存储类型列表
     */
    public java.util.Set<String> getAvailableStorageTypes() {
        return providerMap.keySet();
    }
}
